# numpy和pandas都是基于C语言写的，运算速度相对较快

# numpy是常用于矩阵计算的一个库

import numpy as np

# 创建一个矩阵
array = np.array([[1, 2, 3], [4, 5, 6]])
# 输出矩阵维数
print('矩阵维度: ', array.ndim)
# 输出矩阵形状
print('矩阵形状：', array.shape)
# 输出矩阵大小
print('矩阵大小：', array.size)

# 创建一个序列，并且可以指定类型
a = np.array([2, 3, 4], dtype=np.int)
# 输出序列
print(a)
# 输出矩阵的类型
print(a.dtype)

# 生成0矩阵，3行4列
b = np.zeros((3, 4))
print(b)

# 定义一个元素全部为1的矩阵
c = np.ones((3, 4), dtype=np.int16)
print(c)

# 定义一个空矩阵，但实际不是空，
d = np.empty((3, 4))
print(d)

# 定义一个有序序列，这里起始为10，结束为20（但不包括），步长为2
e = np.arange(10, 20, 2)
print(e)

# 定义一个有序的矩阵，reshape官方是两个括号，使用一个也不会错
f = np.arange(12).reshape((3, 4))
print(f)

# 定义一个线段
g = np.linspace(1, 10, 6)
print(g)
g = g.reshape((2, 3))
print(g)

# numpy的基础运算，关于矩阵的计算可以指定行或者列
a = np.array([10, 20, 30, 40])
b = np.arange(4)

print(a, b)
print(a - b)
print(a + b)
print(b ** 2)
print(b < 3)

a = np.array([[1, 1],
              [0, 1]])
b = np.arange(4).reshape(2, 2)
print(a)
print(b)
# 对应相乘
c = a * b
# 矩阵相乘
c_dot = np.dot(a, b)
c_dot_2 = a.dot(b)
print('对应相乘：\n', c)
print('矩阵相乘：\n', c_dot)
print(c_dot_2)

# 随机创建一个矩阵，数值在0~1之间，参数为矩阵的shape
a = np.random.random((2, 4))
print(a)
print('整个矩阵的最大值：', np.max(a))
print('整个矩阵的和：', np.sum(a))
# 参数axis=0表示对列计算，axis=1表示对行计算
print('矩阵的行和：', np.sum(a, axis=1))
print('矩阵的列最大值：', np.max(a, axis=0))
print('矩阵的行最大值：', np.max(a, axis=1))

# numpy的基础计算2
A = np.arange(2, 14).reshape((3, 4))
print(A)
print('最大值的索引：', np.argmax(A))
print('最小值的索引：', np.argmin(A))
# 求平均值，这些操作均可指定行或者列
print(np.mean(A))
print(np.mean(A, axis=1))
print(A.mean())
print(np.average(A))
# 求中位数
print(np.median(A))
# 累加和
print(np.cumsum(A))
# 求差
print(np.diff(A))
# 求非0元素的行列索引
print(np.nonzero(A))
# 求转置矩阵，下面两个相同
print(np.transpose(A))
print(A.T)
# 矩阵乘法运算
print((A.T).dot(A))
# 限制大小，小于5的元素改为5，大于9的元素改为9
print(np.clip(A, 5, 9))

# numpy的索引
a = np.arange(2, 14)
print(a)
# 输出索引对应的元素，索引从0开始
print(a[3])

# 输出切片
print(a[2:5])

a = np.arange(2, 14).reshape((3, 4))
# 输出一行
print(a[0])
print(a[0, :])

# 输出一列
print(a[:, 0])

# 输出某一个元素
print(a[0][1])
print(a[0, 1])

# 输出某一行的指定长度的数字
print(a[0, 0:2])

# 行循环
for row in a:
    print(row)

# 列循环，没有直接的列循环，需要记住矩阵的转置
for col in a.T:
    print(col)

# 转化为一行序列
print(a.flatten())
# 循环遍历每个元素
for item in a.flat:
    print(item)

# numpy的array合并
a = np.array([1, 1, 1])
b = np.array([2, 2, 2])

# 垂直方向堆叠，变成了2*3的矩阵
c = np.vstack((a, b))
print(c)
print(a.shape, c.shape)

# 水平方向合并，变成了1*6的序列，序列和1维矩阵还是有区别的，shape不一样。[[1,1,1]]是矩阵，[1,1,1]是序列
d = np.hstack((a, b))
print(d)
print(a.shape, d.shape)

# 将a转化为矩阵，在行上加一个维度
print(a[np.newaxis, :].shape)

# 将a转化为矩阵，在列上加一个维度
print(a[:, np.newaxis].shape)

# 多个array合并,axis=0则行数可以变，列数不变；axis=1则列数可以变，行数不变；
a = np.array([1, 1, 1])[np.newaxis, :]
b = np.array([2, 2, 2])[np.newaxis, :]
# a,b需要先从序列转化为矩阵才能进行合并
e = np.concatenate((a, a, b, b), axis=0)
print(a)
print(e)

# numpy的array分割
a = np.arange(12).reshape((3, 4))
print(a)

# axis=1保留行数，拆分为两个3行2列的矩阵
print(np.split(a, 2, axis=1))

# axis=0保留列数，拆分为3个1行3列的矩阵
print(np.split(a, 3, axis=0))

# 不等量分割，4列矩阵拆分为3个矩阵，列数为2，1，1
print(np.array_split(a, 3, axis=1))

# 纵向分割
print(np.vsplit(a, 3))

# 横向分割
print(np.hsplit(a, 2))

# array的深浅复制
a = np.array([1, 2, 3, 4])
print(a)

# 浅复制，a，b指向同一块内存地址
b = a
# 改变b中的值，a中的值也会变
b[0] = 5
print(a)
print(b)

# 深复制,a,b指向不同的内存地址
b = a.copy()
b[0] = 6
print(a)
print(b)
